package com.liu.hashmap;

/**
 * @author LIU
 * @version 1.0
 * @description TODO
 * @date 2024/2/5 9:59
 */
public class MyHashMap<K, V> implements MyMap<K, V> {
    int size;

    Node<K, V>[] table = null;

    public MyHashMap() {
        table = new Node[16];
    }

    /**
     * @description 1.key进行hash 取模算出index下标
     * 数组节点对象是否为空
     * 如果为空 赋值存储
     * 如果不为空 hash冲突 链表存储
     * @author liuzq
     * @date 2024/2/5 10:05
     */
    @Override
    public V put(K k, V v) {
        int index = hash(k);
        Node<K, V> node = table[index];
        if (null == node) {
            table[index] = new Node<>(index, k, v, null);
            size++;
        } else {
            table[index] = new Node<>(index, k, v, node);
        }
        return null;
    }

    /**
     * @param key
     * @return V
     * @description TODO
     * key 进行hash 得到index下标
     * 根据下标得到节点对象，如果为空直接返回null
     * 如果不为空 key与当前key进行比较
     * 如果相等 直接返回数据
     * @author liuzq
     * @date 2024/2/5 10:31
     */
    @Override
    public V get(K key) {
        int index = hash(key);
        Node<K, V>  node = findNode(key, table[index]);
        return node== null ? null:node.getValue();

    }

    private Node<K, V>  findNode(K key, Node<K, V> node) {
        if (null == node) {
            return null;
        }
        if (key.equals(node.getKey()) || key == node.getKey()){
            return node;
        }else {
            if (null !=node.next){
                return findNode(key, node.next);
            }else {
                return null;
            }
        }
    }



    @Override
    public int size() {
        return size;
    }


    private int hash(Object key) {
        int index = key.hashCode() % 16 -1;
        return index > 0 ? index : -index;
    }


    class Node<K, V> implements Entry<K, V> {

        final int hash;

        final K key;

        V value;

        Node<K, V> next;

        public Node(int hash, K key, V value, Node<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }
    }
}
